package edu.ccut.saturn.component.impl;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

import edu.ccut.saturn.component.IComponent;
import edu.ccut.saturn.component.IConnectionInfo;
import edu.ccut.saturn.component.ILogicComponentInfo;
import edu.ccut.saturn.component.INodeInfo;
import edu.ccut.saturn.component.IParameterInfo;
import edu.ccut.saturn.component.SaturnComponentException;
import edu.ccut.saturn.component.loader.ComponentLoader;
import edu.ccut.saturn.component.xml.ISaturnElement;
import edu.ccut.saturn.component.xml.SaturnElement;

/**
 * {@link ILogicComponentInfo} implementation
 * 
 * @see ILogicComponentInfos
 * @author LeslieGu
 * 
 */
public class SaturnLogicComponentInfo extends AbstractComponentInfo implements
		ILogicComponentInfo {

	private Map<String, INodeInfo> nodeMap;

	private INodeInfo startNodeInfo;

	private List<IConnectionInfo> connectionInfos;

	public SaturnLogicComponentInfo(String symbolicName, String key,
			String name, String description, String loadStart) {

		super(symbolicName, key, name, description, null, loadStart);
		this.nodeMap = new HashMap<String, INodeInfo>();
	}

	public List<IConnectionInfo> getConnectionInfos() {
		return connectionInfos;
	}

	public void setConnectionInfos(List<IConnectionInfo> connectionInfos) {
		this.connectionInfos = connectionInfos;
	}

	public INodeInfo getNodeInfo(String id) {
		return this.nodeMap.get(id);
	}

	public void addNodeInfos(List<INodeInfo> nodes)
			throws SaturnComponentException {

		if (nodes != null) {

			for (INodeInfo nodeInfo : nodes) {
				this.addNodoInfo(nodeInfo);
			}
		}
	}

	public void addNodoInfo(INodeInfo nodeInfo) throws SaturnComponentException {

		if (this.nodeMap.containsKey(nodeInfo.getId())) {
			throw new SaturnComponentException("error! the node id = "
					+ nodeInfo.getId() + " is duplicate!");
		}

		this.nodeMap.put(nodeInfo.getId(), nodeInfo);
	}

	public INodeInfo getStartNodeInfo() {
		return this.startNodeInfo;
	}

	public void setStartNodeInfo(INodeInfo nodeInfo) {
		this.startNodeInfo = nodeInfo;
	}

	public IComponent createComponent() throws SaturnComponentException {
		// logger.debug("create logic component \"" + super.getFullKey() +
		// "\"");
		return new SaturnLogicComponent(this);
	}

	@Override
	public List<IParameterInfo> getParameterInfos() {
		return this.getStartNodeInfo().getParameterInfos();
	}

	public Set<String> getNodeIdKeySet() {
		return this.nodeMap.keySet();
	}

	public ISaturnElement toSaturnElement() {
		ISaturnElement saturnLogicElement = getRootElement();
		ISaturnElement informationElement = getInformationElement();
		saturnLogicElement.addSubElement(informationElement);

		if (startNodeInfo != null) {
			saturnLogicElement.addSubElement(startNodeInfo.toSaturnElement());
		}

		for (String key : this.nodeMap.keySet()) {
			saturnLogicElement.addSubElement(this.nodeMap.get(key)
					.toSaturnElement());

		}

		if (this.connectionInfos != null) {

			for (IConnectionInfo connectionInfo : this.connectionInfos) {
				saturnLogicElement.addSubElement(connectionInfo
						.toSaturnElement());
			}
		}
		return saturnLogicElement;
	}

	protected ISaturnElement getRootElement() {
		ISaturnElement saturnLogicElement = new SaturnElement(
				ComponentLoader.KEY_LOGIC_ROOT);

		return saturnLogicElement;
	}

	protected ISaturnElement getInformationElement() {
		ISaturnElement informationElement = new SaturnElement(
				ComponentLoader.KEY_INFORMATION);

		informationElement.addAttribute("next", "");
		informationElement.addAttribute("x", "0");
		informationElement.addAttribute("y", "0");
		informationElement.addAttribute("id", "0");

		ISaturnElement keyElement = new SaturnElement(
				ComponentLoader.KEY_MODULE_KEY, this.getKey());

		ISaturnElement nameElement = new SaturnElement(
				ComponentLoader.KEY_MODULE_NAME, this.getName());

		ISaturnElement descriptionElement = new SaturnElement(
				ComponentLoader.KEY_MODULE_DESCRIPTION, this.getDescription());
		
		ISaturnElement loadstartElement = new SaturnElement(
				ComponentLoader.KEY_COMPONENT_LOADSTART, this.getLoadStart());

		informationElement.addSubElement(keyElement);
		informationElement.addSubElement(nameElement);
		informationElement.addSubElement(descriptionElement);
		informationElement.addSubElement(loadstartElement);
		
		return informationElement;
	}
}
